package org.nifi.processors;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import lombok.RequiredArgsConstructor;
import org.nifi.processors.config.DataAccessConst;
import org.nifi.processors.config.DataAccessException;
import org.nifi.processors.config.DataAccessProperties;
import org.nifi.processors.config.SignHttpInterceptor;
import org.nifi.processors.model.Res;
import org.nifi.processors.model.ResToken;
import org.nifi.processors.utils.HttpUtils;
import org.nifi.processors.utils.JsonUtils;

import java.util.Map;
import java.util.Objects;

@RequiredArgsConstructor
public class DataAccessService {

    private final DataAccessProperties properties;

    /**
     * 获取令牌, 独立写，防止出现循环依赖
     * TODO 可以自行增加缓存
     *
     * @return token信息
     */
    public String token() {
        HttpResponse httpResponse = HttpUtil.createPost(properties.getTokenFullUrl())
                .timeout((int) properties.getTimeout().toMillis())
                .addRequestInterceptor(new SignHttpInterceptor(properties))
                .execute();
        Res res = HttpUtils.parse(httpResponse);
        if (Objects.isNull(res.getRetData())) {
            return null;
        }
        ResToken resToken = JsonUtils.deserializeJson(JsonUtils.serializeJson(res.getRetData()), ResToken.class);
        String tokenStr = Objects.isNull(resToken) ? null : resToken.getToken();
        System.out.println("token = " + tokenStr);
        return tokenStr;
    }


    /**
     * 请求方式
     *
     * @param url   请求地址
     * @param value 请求参数。可以为字符串或对象
     * @return 结果
     */
    public Res post(String url, Object value) {
        return post(url, value, MapUtil.newHashMap(), false);
    }

    /**
     * 请求方式
     *
     * @param url     请求地址
     * @param value   请求参数。可以为字符串或对象
     * @param headers 请求头
     * @return 结果
     */
    public Res post(String url, Object value, Map<String, String> headers) {
        return post(url, value, headers, false);
    }

    /**
     * 请求方式
     *
     * @param url       请求地址
     * @param value     请求参数。可以为字符串或对象
     * @param autoToken 自动token
     * @return 结果
     */
    public Res post(String url, Object value, boolean autoToken) {
        return post(url, value, MapUtil.newHashMap(), autoToken);
    }

    /**
     * 请求方式
     *
     * @param url       请求地址
     * @param value     请求参数。可以为字符串或对象
     * @param headers   请求头
     * @param autoToken 自动token
     * @return 结果
     */
    public Res post(String url, Object value, Map<String, String> headers, boolean autoToken) {
        Assert.notEmpty(url, () -> new IllegalArgumentException("请求URL不能为空"));
        // 追加地址
        url = StrUtil.addPrefixIfNot(url, properties.getAddress());
        HttpRequest httpRequest = HttpUtil.createPost(url).formStr(HttpUtils.buildFormParam(value))
                .headerMap(headers, true)
                .timeout((int) properties.getTimeout().toMillis())
                .addRequestInterceptor(new SignHttpInterceptor(properties));
        // 自动token
        if (autoToken) {
            httpRequest.auth(token());
        }
        try {
            return HttpUtils.parse(httpRequest.execute());
        } catch (DataAccessException e) {
            // 调用token失效时再次调用一下
            if (autoToken && Objects.equals(e.getCode(), DataAccessConst.TOKEN_EXPIRE)) {
                httpRequest.auth(token());
                return HttpUtils.parse(httpRequest.execute());
            }
            throw e;
        }
    }

}
